home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / MPW_TOOL / TOOLS / TOOLS_WI / FAST_LEX / MAIN.C < prev    next >
C/C++ Source or Header  |  1988-07-04  |  14KB  |  583 lines

  1. /* flex - tool to generate fast lexical analyzers
  2.  *
  3.  *
  4.  * Copyright (c) 1987, the University of California
  5.  * 
  6.  * The United States Government has rights in this work pursuant to
  7.  * contract no. DE-AC03-76SF00098 between the United States Department of
  8.  * Energy and the University of California.
  9.  * 
  10.  * This program may be redistributed.  Enhancements and derivative works
  11.  * may be created provided the new works, if made available to the general
  12.  * public, are made available for use by anyone.
  13.  *
  14.  *
  15.  * ver   date  who    remarks
  16.  * ---   ----  ------ -------------------------------------------------------
  17.  * 04b 30sep87 kg, vp .implemented (part of) Van Jacobson's fast scanner design
  18.  * 04a 27jun86 vp     .translated from Ratfor into C
  19.  * 01a 22aug83 vp     .written.  Original version by Jef Poskanzer.
  20.  */
  21.  
  22. #include "flexdef.h"
  23.  
  24.  
  25. /* these globals are all defined and commented in flexdef.h */
  26. int printstats, syntaxerror, eofseen, ddebug, trace, spprdflt;
  27. int interactive, caseins, useecs, fulltbl, usemecs, reject;
  28. int fullspd, gen_line_dirs;
  29. int datapos, dataline, linenum;
  30. FILE *skelfile = NULL;
  31. char *infilename = NULL;
  32. #ifdef MALLOC_BUFFERS
  33. int *onestate,*onesym,*onenext,*onedef,onesp;
  34. #else
  35. int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
  36. int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
  37. #endif
  38. int current_mns;
  39. int accnum, *firstst, *lastst, *finalst, *transchar;
  40. int *trans1, *trans2, *accptnum, lastnfa;
  41. #ifdef MALLOC_BUFFERS
  42. int numtemps, numprots, *protprev, *protnext, *prottbl;
  43. int *protcomst, firstprot, lastprot,
  44. #else
  45. int numtemps, numprots, protprev[MSP], protnext[MSP], prottbl[MSP];
  46. int protcomst[MSP], firstprot, lastprot,
  47. #endif
  48. #ifdef MALLOC_BUFFERS
  49.     *protsave;
  50. #else
  51.     protsave[PROT_SAVE_SIZE];
  52. #endif
  53. #ifdef MALLOC_BUFFERS
  54. int numecs, *nextecm, *ecgroup, nummecs;
  55. int *tecfwd, *tecbck;
  56. #else
  57. int numecs, nextecm[CSIZE + 1], ecgroup[CSIZE + 1], nummecs;
  58. int tecfwd[CSIZE + 1], tecbck[CSIZE + 1];
  59. #endif
  60. int lastsc, current_max_scs, *scset, *scbol, *scxclu, *actvsc;
  61. int current_max_dfa_size, current_max_xpairs;
  62. int current_max_template_xpairs, current_max_dfas;
  63. int lastdfa, *nxt, *chk, *tnxt;
  64. int *base, *def, tblend, firstfree, numtemps, **dss, *dfasiz;
  65. union dfaacc_union *dfaacc;
  66. int *accsiz, *dhash, *todo, todo_head, todo_next, numas;
  67. int numsnpairs, jambase, jamstate;
  68. int lastccl, current_maxccls, *cclmap, *ccllen, *cclng, cclreuse;
  69. int current_max_ccl_tbl_size;
  70. char *ccltbl;
  71. char *starttime, *endtime, nmstr[MAXLINE];
  72. int sectnum, nummt, hshcol, dfaeql, numeps, eps2, num_reallocs;
  73. int tmpuses, totnst, peakpairs, numuniq, numdup, hshsave;
  74. FILE *temp_action_file;
  75. int end_of_buffer_state;
  76. char *action_file_name = "/tmp/flexXXXXXX";
  77.  
  78.  
  79. /* flex - main program
  80.  *
  81.  * synopsis (from the shell)
  82.  *    flex [-v] [file ...]
  83.  */
  84.  
  85. main( argc, argv )
  86. int argc;
  87. char **argv;
  88.  
  89.     {
  90. #ifdef MALLOC_BUFFERS
  91. #define GETBUF(a,b) a = (int *)(malloc((b)*sizeof(int)))
  92.     GETBUF(onestate,ONE_STACK_SIZE);
  93.     GETBUF(onesym,ONE_STACK_SIZE);
  94.     GETBUF(onenext,ONE_STACK_SIZE);
  95.     GETBUF(onedef,ONE_STACK_SIZE);
  96.     GETBUF(protprev,MSP);
  97.     GETBUF(protnext,MSP);
  98.     GETBUF(prottbl,MSP);
  99.     GETBUF(protcomst,MSP);
  100.     GETBUF(protsave,PROT_SAVE_SIZE);
  101.     GETBUF(nextecm,CSIZE + 1);
  102.     GETBUF(ecgroup,CSIZE + 1);
  103.     GETBUF(tecfwd,CSIZE + 1);
  104.     GETBUF(tecbck,CSIZE + 1);
  105.     if(onestate == NULL || onesym == NULL || onenext == NULL || onedef
  106.         == NULL || protprev == NULL || protnext  == NULL || prottbl  == NULL || 
  107.         protcomst == NULL || protsave == NULL || nextecm  == NULL || ecgroup 
  108.         == NULL || tecfwd == NULL || tecbck == NULL){
  109.         fprintf(stderr,"%s: Out of memory\n",argv[0]);
  110.         exit(-1);
  111.     }
  112. #endif
  113.     flexinit( argc, argv );
  114.  
  115.     readin();
  116.  
  117.     if ( ! syntaxerror )
  118.     {
  119.     /* convert the ndfa to a dfa */
  120.     ntod();
  121.  
  122.     /* generate the C state transition tables from the DFA */
  123.     make_tables();
  124.     }
  125.  
  126.     /* note, flexend does not return.  It exits with its argument as status. */
  127.  
  128.     flexend( 0 );
  129.     }
  130.  
  131.  
  132. /* flexend - terminate flex
  133.  *
  134.  * synopsis
  135.  *    int status;
  136.  *    flexend( status );
  137.  *
  138.  *    status is exit status.
  139.  *
  140.  * note
  141.  *    This routine does not return.
  142.  */
  143.  
  144. flexend( status )
  145. int status;
  146.  
  147.     {
  148.     int tblsiz;
  149.     char *gettime();
  150.  
  151.     if ( skelfile != NULL )
  152.     (void) fclose( skelfile );
  153.  
  154.     if ( temp_action_file )
  155.     {
  156.     (void) fclose( temp_action_file );
  157.     (void) unlink( action_file_name );
  158.     }
  159.  
  160.     if ( printstats )
  161.     {
  162.     endtime = gettime();
  163.  
  164.     fprintf( stderr, "flex usage statistics:\n" );
  165.     fprintf( stderr, "  started at %s, finished at %s\n",
  166.          starttime, endtime );
  167.  
  168.     fprintf( stderr, "  %d/%d NFA states\n", lastnfa, current_mns );
  169.     fprintf( stderr, "  %d/%d DFA states (%d words)\n", lastdfa,
  170.              current_max_dfas, totnst );
  171.     fprintf( stderr, "  %d rules\n", accnum );
  172.     fprintf( stderr, "  %d/%d start conditions\n", lastsc,
  173.              current_max_scs );
  174.     fprintf( stderr, "  %d epsilon states, %d double epsilon states\n",
  175.          numeps, eps2 );
  176.  
  177.     if ( lastccl == 0 )
  178.         fprintf( stderr, "  no character classes\n" );
  179.     else
  180.         fprintf( stderr,
  181.     "  %d/%d character classes needed %d/%d words of storage, %d reused\n",
  182.              lastccl, current_maxccls,
  183.              cclmap[lastccl] + ccllen[lastccl] - 1,
  184.              current_max_ccl_tbl_size, cclreuse );
  185.  
  186.     fprintf( stderr, "  %d state/nextstate pairs created\n", numsnpairs );
  187.     fprintf( stderr, "  %d/%d unique/duplicate transitions\n",
  188.          numuniq, numdup );
  189.  
  190.     if ( fulltbl )
  191.         {
  192.         tblsiz = lastdfa * numecs;
  193.         fprintf( stderr, "  %d table entries\n", tblsiz );
  194.         }
  195.  
  196.     else
  197.         {
  198.         tblsiz = 2 * (lastdfa + numtemps) + 2 * tblend;
  199.  
  200.         fprintf( stderr, "  %d/%d base/def entries created\n",
  201.              lastdfa + numtemps, current_max_dfas );
  202.         fprintf( stderr, "  %d/%d (peak %d) nxt/chk entries created\n",
  203.              tblend, current_max_xpairs, peakpairs );
  204.         fprintf( stderr,
  205.              "  %d/%d (peak %d) template nxt/chk entries created\n",
  206.              numtemps * nummecs, current_max_template_xpairs,
  207.              numtemps * numecs );
  208.         fprintf( stderr, "  %d empty table entries\n", nummt );
  209.         fprintf( stderr, "  %d protos created\n", numprots );
  210.         fprintf( stderr, "  %d templates created, %d uses\n",
  211.              numtemps, tmpuses );
  212.         }
  213.  
  214.     if ( useecs )
  215.         {
  216.         tblsiz = tblsiz + CSIZE;
  217.         fprintf( stderr, "  %d/%d equivalence classes created\n",
  218.              numecs, CSIZE );
  219.         }
  220.  
  221.     if ( usemecs )
  222.         {
  223.         tblsiz = tblsiz + numecs;
  224.         fprintf( stderr, "  %d/%d meta-equivalence classes created\n",
  225.              nummecs, CSIZE );
  226.         }
  227.  
  228.     fprintf( stderr, "  %d (%d saved) hash collisions, %d DFAs equal\n",
  229.          hshcol, hshsave, dfaeql );
  230.     fprintf( stderr, "  %d sets of reallocations needed\n", num_reallocs );
  231.     fprintf( stderr, "  %d total table entries needed\n", tblsiz );
  232.     }
  233.  
  234.     exit( status );
  235.     }
  236.  
  237.  
  238. /* flexinit - initialize flex
  239.  *
  240.  * synopsis
  241.  *    int argc;
  242.  *    char **argv;
  243.  *    flexinit( argc, argv );
  244.  */
  245.  
  246. flexinit( argc, argv )
  247. int argc;
  248. char **argv;
  249.  
  250.     {
  251.     int i, sawcmpflag, use_stdout;
  252.     char *arg, *skelname = NULL, *gettime(), clower(), *mktemp();
  253.  
  254.     printstats = syntaxerror = trace = spprdflt = interactive = caseins = false;
  255.     ddebug = fulltbl = reject = fullspd = false;
  256.     gen_line_dirs = usemecs = useecs = true;
  257.  
  258.     sawcmpflag = false;
  259.     use_stdout = false;
  260.  
  261.     /* read flags */
  262.     for ( --argc, ++argv; argc ; --argc, ++argv )
  263.     {
  264.     if ( argv[0][0] != '-' || argv[0][1] == '\0' )
  265.         break;
  266.  
  267.     arg = argv[0];
  268.  
  269.     for ( i = 1; arg[i] != '\0'; ++i )
  270.         switch ( arg[i] )
  271.         {
  272.         case 'c':
  273.             if ( i != 1 )
  274.             flexerror( "-c flag must be given separately" );
  275.  
  276.             if ( ! sawcmpflag )
  277.             {
  278.             useecs = false;
  279.             usemecs = false;
  280.             fulltbl = false;
  281.             sawcmpflag = true;
  282.             }
  283.  
  284.             for ( ++i; arg[i] != '\0'; ++i )
  285.             switch ( clower( arg[i] ) )
  286.                 {
  287.                 case 'e':
  288.                 useecs = true;
  289.                 break;
  290.  
  291.                 case 'F':
  292.                 fullspd = true;
  293.                 break;
  294.  
  295.                 case 'f':
  296.                 fulltbl = true;
  297.                 break;
  298.  
  299.                 case 'm':
  300.                 usemecs = true;
  301.                 break;
  302.  
  303.                 default:
  304.                 lerrif( "unknown -c option %c",
  305.                     (int) arg[i] );
  306.                 break;
  307.                 }
  308.             
  309.             goto get_next_arg;
  310.  
  311.         case 'd':
  312.             ddebug = true;
  313.             break;
  314.  
  315.         case 'f':
  316.             useecs = usemecs = false;
  317.             fulltbl = true;
  318.             break;
  319.  
  320.         case 'I':
  321.             interactive = true;
  322.             break;
  323.  
  324.         case 'i':
  325.             caseins = true;
  326.             break;
  327.  
  328.         case 'L':
  329.             gen_line_dirs = false;
  330.             break;
  331.  
  332.         case 'r':
  333.             reject = true;
  334.             break;
  335.  
  336.         case 'F':
  337.             useecs = usemecs = false;
  338.             fullspd = true;
  339.             break;
  340.  
  341.         case 'S':
  342.             if ( i != 1 )
  343.             flexerror( "-S flag must be given separately" );
  344.  
  345.             skelname = arg + i + 1;
  346.             goto get_next_arg;
  347.  
  348.         case 's':
  349.             spprdflt = true;
  350.             break;
  351.  
  352.         case 't':
  353.             use_stdout = true;
  354.             break;
  355.  
  356.         case 'T':
  357.             trace = true;
  358.             break;
  359.  
  360.         case 'v':
  361.             printstats = true;
  362.             break;
  363.  
  364.         default:
  365.             lerrif( "unknown flag %c", (int) arg[i] );
  366.             break;
  367.         }
  368.  
  369. get_next_arg: /* used by -c and -S flags in lieu of a "continue 2" control */
  370.     ;
  371.     }
  372.  
  373.     if ( (fulltbl || fullspd) && usemecs )
  374.     flexerror( "full table and -cm don't make sense together" );
  375.  
  376.     if ( (fulltbl || fullspd) && interactive )
  377.     flexerror( "full table and -I are (currently) incompatible" );
  378.  
  379.     if ( (fulltbl || fullspd) && reject )
  380.     flexerror( "reject (-r) cannot be used with -f or -F" );
  381.  
  382.     if ( fulltbl && fullspd )
  383.     flexerror( "full table and -F are mutually exclusive" );
  384.  
  385.     if ( ! skelname )
  386.     {
  387.     static char skeleton_name_storage[400];
  388.  
  389.     skelname = skeleton_name_storage;
  390.  
  391.     if ( fullspd || fulltbl )
  392.         (void) strcpy( skelname, FAST_SKELETON_FILE );
  393.     else
  394.         (void) strcpy( skelname, DEFAULT_SKELETON_FILE );
  395.     }
  396.  
  397.     if ( ! use_stdout )
  398.     {
  399.     FILE *prev_stdout = freopen( "lex.yy.c", "w", stdout );
  400.  
  401.     if ( prev_stdout == NULL )
  402.         flexerror( "could not create lex.yy.c" );
  403.     }
  404.  
  405.     if ( argc )
  406.     {
  407.     if ( argc > 1 )
  408.         flexerror( "extraneous argument(s) given" );
  409.  
  410.     yyin = fopen( infilename = argv[0], "r" );
  411.  
  412.     if ( yyin == NULL )
  413.         lerrsf( "can't open %s", argv[0] );
  414.     }
  415.  
  416.     else
  417.     yyin = stdin;
  418.  
  419.     lastccl = 0;
  420.     lastsc = 0;
  421.  
  422.     /* initialize the statistics */
  423.     starttime = gettime();
  424.  
  425.     if ( (skelfile = fopen( skelname, "r" )) == NULL )
  426.     lerrsf( "can't open skeleton file %s", skelname );
  427.  
  428. #ifndef MPW            /* Single-user system. */
  429.     (void) mktemp( action_file_name );
  430. #endif
  431.  
  432.     if ( (temp_action_file = fopen( action_file_name, "w" )) == NULL )
  433.     lerrsf( "can't open temporary action file %s", action_file_name );
  434.  
  435.     lastdfa = lastnfa = accnum = numas = numsnpairs = tmpuses = 0;
  436.     numecs = numeps = eps2 = num_reallocs = hshcol = dfaeql = totnst = 0;
  437.     numuniq = numdup = hshsave = eofseen = datapos = dataline = 0;
  438.     onesp = numprots = 0;
  439.  
  440.     linenum = sectnum = 1;
  441.     firstprot = NIL;
  442.  
  443.     /* used in mkprot() so that the first proto goes in slot 1
  444.      * of the proto queue
  445.      */
  446.     lastprot = 1;
  447.  
  448.     if ( useecs )
  449.     {
  450.     /* set up doubly-linked equivalence classes */
  451.     ecgroup[1] = NIL;
  452.  
  453.     for ( i = 2; i <= CSIZE; ++i )
  454.         {
  455.         ecgroup[i] = i - 1;
  456.         nextecm[i - 1] = i;
  457.         }
  458.  
  459.     nextecm[CSIZE] = NIL;
  460.     }
  461.  
  462.     else
  463.     { /* put everything in its own equivalence class */
  464.     for ( i = 1; i <= CSIZE; ++i )
  465.         {
  466.         ecgroup[i] = i;
  467.         nextecm[i] = BAD_SUBSCRIPT;    /* to catch errors */
  468.         }
  469.     }
  470.  
  471.     set_up_initial_allocations();
  472.     }
  473.  
  474.  
  475. /* readin - read in the rules section of the input file(s)
  476.  *
  477.  * synopsis
  478.  *    readin();
  479.  */
  480.  
  481. readin()
  482.  
  483.     {
  484.     fputs( "#define YY_DEFAULT_ACTION ", stdout );
  485.  
  486.     if ( spprdflt )
  487.     fputs( "YY_FATAL_ERROR( \"flex scanner jammed\" )", stdout );
  488.     else
  489.     fputs( "ECHO", stdout );
  490.  
  491.     fputs( ";\n", stdout );
  492.  
  493.     if ( ddebug )
  494.     puts( "#define FLEX_DEBUG" );
  495.     if ( useecs )
  496.     puts( "#define FLEX_USE_ECS" );
  497.     if ( usemecs )
  498.     puts( "#define FLEX_USE_MECS" );
  499.     if ( interactive )
  500.     puts( "#define FLEX_INTERACTIVE_SCANNER" );
  501.     if ( reject )
  502.     puts( "#define FLEX_REJECT_ENABLED" );
  503.     if ( fulltbl )
  504.     puts( "#define FLEX_FULL_TABLE" );
  505.  
  506.     skelout();
  507.  
  508.     line_directive_out( stdout );
  509.  
  510.     if ( yyparse() )
  511. #ifdef MPW        /* See tool interface guidelines in MPW manual. */
  512.     {
  513.         char *panicmsg;
  514.         char *alloca();
  515.         panicmsg = alloca(128);
  516.         sprintf(panicmsg,"File %s ; %%d # Fatal parse error.");
  517.         lerrif(panicmsg,linenum);
  518.     }
  519. #else
  520.     lerrif( "fatal parse error at line %d", linenum );
  521. #endif
  522.  
  523.     if ( useecs )
  524.     {
  525.     numecs = cre8ecs( nextecm, ecgroup, CSIZE );
  526.     ccl2ecl();
  527.     }
  528.  
  529.     else
  530.     numecs = CSIZE;
  531.  
  532.     }
  533.  
  534.  
  535.  
  536. /* set_up_initial_allocations - allocate memory for internal tables */
  537.  
  538. set_up_initial_allocations()
  539.  
  540.     {
  541.     current_mns = INITIAL_MNS;
  542.     firstst = allocate_integer_array( current_mns );
  543.     lastst = allocate_integer_array( current_mns );
  544.     finalst = allocate_integer_array( current_mns );
  545.     transchar = allocate_integer_array( current_mns );
  546.     trans1 = allocate_integer_array( current_mns );
  547.     trans2 = allocate_integer_array( current_mns );
  548.     accptnum = allocate_integer_array( current_mns );
  549.  
  550.     current_max_scs = INITIAL_MAX_SCS;
  551.     scset = allocate_integer_array( current_max_scs );
  552.     scbol = allocate_integer_array( current_max_scs );
  553.     scxclu = allocate_integer_array( current_max_scs );
  554.     actvsc = allocate_integer_array( current_max_scs );
  555.  
  556.     current_maxccls = INITIAL_MAXCCLS;
  557.     cclmap = allocate_integer_array( current_maxccls );
  558.     ccllen = allocate_integer_array( current_maxccls );
  559.     cclng = allocate_integer_array( current_maxccls );
  560.  
  561.     current_max_ccl_tbl_size = INITIAL_MAX_CCL_TBL_SIZE;
  562.     ccltbl = allocate_character_array( current_max_ccl_tbl_size );
  563.  
  564.     current_max_dfa_size = INITIAL_MAX_DFA_SIZE;
  565.  
  566.     current_max_xpairs = INITIAL_MAX_XPAIRS;
  567.     nxt = allocate_integer_array( current_max_xpairs );
  568.     chk = allocate_integer_array( current_max_xpairs );
  569.  
  570.     current_max_template_xpairs = INITIAL_MAX_TEMPLATE_XPAIRS;
  571.     tnxt = allocate_integer_array( current_max_template_xpairs );
  572.  
  573.     current_max_dfas = INITIAL_MAX_DFAS;
  574.     base = allocate_integer_array( current_max_dfas );
  575.     def = allocate_integer_array( current_max_dfas );
  576.     dfasiz = allocate_integer_array( current_max_dfas );
  577.     accsiz = allocate_integer_array( current_max_dfas );
  578.     dhash = allocate_integer_array( current_max_dfas );
  579.     todo = allocate_integer_array( current_max_dfas );
  580.     dss = allocate_integer_pointer_array( current_max_dfas );
  581.     dfaacc = allocate_dfaacc_union( current_max_dfas );
  582.     }
  583.